package org.ffmmx.launcher;

import org.ffmmx.gxhotel.inteceptor.TokenValidatorInterceptor;
import org.ffmmx.gxhotel.model.hotelbs.Cguester;
import org.ffmmx.gxhotel.model.specialuserout.Stationlist;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.boot.autoconfigure.jdbc.DataSourceBuilder;
import org.springframework.boot.autoconfigure.orm.jpa.JpaProperties;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

import javax.persistence.EntityManager;
import javax.sql.DataSource;
import java.util.Map;

@SpringBootApplication
@ComponentScan(value = "org.ffmmx")
@EntityScan(value = "org.ffmmx")
@Configuration
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

    @Configuration
    class DataSourceConfig {
        @Bean
        @Qualifier("specialuseroutDataSource")
        @ConfigurationProperties(prefix = "spring.datasource.specialuserout")
        public DataSource specialuseroutDataSource() {
            return DataSourceBuilder.create().build();
        }

        @Bean
        @Qualifier("hotelbsDataSource")
        @ConfigurationProperties(prefix = "spring.datasource.hotelbs")
        @Primary
        public DataSource hotelbsDataSource() {
            return DataSourceBuilder.create().build();
        }


    }

    @Configuration
    @EnableTransactionManagement
    @EnableJpaRepositories(
            entityManagerFactoryRef="entityManagerFactoryPrimary",
            transactionManagerRef="transactionManagerPrimary",
            basePackages= {"org.ffmmx.gxhotel.repository.cguester"}
    )
    class HotelbsConfig {
        @Autowired
        @Qualifier("hotelbsDataSource")
        private DataSource hotelbsDataSource;

        @Primary
        @Bean
        public LocalContainerEntityManagerFactoryBean entityManagerFactoryPrimary(org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder builder){
            return builder.dataSource(hotelbsDataSource)
                    .packages(Cguester.class)
                    .properties(getVendorProperties(hotelbsDataSource))
                    .persistenceUnit("hotelbs")
                    .build();
        }

        @Primary
        @Bean
        public EntityManager entityManager(org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder builder){
            return entityManagerFactoryPrimary(builder).getObject().createEntityManager();
        }

        @Autowired
        private JpaProperties jpaProperties;

        private Map<String, String> getVendorProperties(DataSource dataSource) {
            return jpaProperties.getHibernateProperties(dataSource);
        }


        @Primary
        @Bean
        public PlatformTransactionManager transactionManagerPrimary(EntityManagerFactoryBuilder builder) {
            return new JpaTransactionManager(entityManagerFactoryPrimary(builder).getObject());
        }

    }

    @Configuration
    @EnableTransactionManagement
    @EnableJpaRepositories(
            entityManagerFactoryRef="entityManagerFactorySecond",
            transactionManagerRef="transactionManagerSecond",
            basePackages= {"org.ffmmx.gxhotel.repository.stationlist"}
    )
    class SpecialuseroutConfig {
        @Autowired
        @Qualifier("specialuseroutDataSource")
        private DataSource specialuseroutDataSource;

        @Bean
        public LocalContainerEntityManagerFactoryBean entityManagerFactorySecond(EntityManagerFactoryBuilder builder){
            return builder.dataSource(specialuseroutDataSource)
                    .packages(Stationlist.class)
                    .properties(getVendorProperties(specialuseroutDataSource))
                    .persistenceUnit("specialuserout")
                    .build();
        }

        @Bean
        public EntityManager entityManager(EntityManagerFactoryBuilder builder){
            return entityManagerFactorySecond(builder).getObject().createEntityManager();
        }

        @Autowired
        private JpaProperties jpaProperties;

        private Map<String, String> getVendorProperties(DataSource dataSource) {
            return jpaProperties.getHibernateProperties(dataSource);
        }


        @Bean
        public PlatformTransactionManager transactionManagerSecond(EntityManagerFactoryBuilder builder) {
            return new JpaTransactionManager(entityManagerFactorySecond(builder).getObject());
        }
    }

    @Configuration
    class WebMvcConfig extends WebMvcConfigurerAdapter {
        @Override
        public void addInterceptors(InterceptorRegistry registry) {
            super.addInterceptors(registry);
            registry.addInterceptor(new TokenValidatorInterceptor())
                    .addPathPatterns("/api/**");
        }
    }
}
